package client;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.*;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.ConsoleHandler;
import java.util.logging.FileHandler;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;

import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpExchange;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;

import data.DownloadBatch_Input;
import data.DownloadBatch_Output;
import data.GetFields_Input;
import data.GetFields_Output;
import data.GetProjects_Output;
import data.GetSampleImage_Input;
import data.GetSampleImage_Output;
import data.Search_Input;
import data.Search_Output;
import data.SubmitBatch_Input;
import data.SubmitBatch_Output;
import data.User;
import data.ValidateUser_Input;
import data.ValidateUser_Output;

public class ServerCommunicator {
	private String request;
	private URL baseURL;
	private XStream xmlStream;
	private static Logger logger;

	static {
		try {
			initLog();
		} catch (IOException e) {
			System.out.println("Could not initialize log: " + e.getMessage());
		}
	}

	private static void initLog() throws IOException {

		Level logLevel = Level.FINE;

		logger = Logger.getLogger("record-indexer");
		logger.setLevel(logLevel);
		logger.setUseParentHandlers(false);

		Handler consoleHandler = new ConsoleHandler();
		consoleHandler.setLevel(logLevel);
		consoleHandler.setFormatter(new SimpleFormatter());
		logger.addHandler(consoleHandler);

		FileHandler fileHandler = new FileHandler("log.txt", false);
		fileHandler.setLevel(logLevel);
		fileHandler.setFormatter(new SimpleFormatter());
		logger.addHandler(fileHandler);
	}

	public ServerCommunicator(int in_port, String in_host) {
		try {
			baseURL = new URL("http://" + in_host + ":" + in_port);
			xmlStream = new XStream(new DomDriver());
		} catch (MalformedURLException e) {
			e.printStackTrace();
		}
	}

	private Object doPost(String urlPath, Object postData) {
		try {
			URL url = new URL(baseURL, urlPath);
			HttpURLConnection connection = (HttpURLConnection) url
					.openConnection();

			connection.setRequestMethod("POST");
			connection.setDoOutput(true);

			String serialized = xmlStream.toXML(postData);
			byte[] toSend = serialized.getBytes();

			connection.connect();
			
			OutputStream requestBody = connection.getOutputStream();

			requestBody.write(toSend);
			requestBody.close();

			Map<String, List<String>> headers = connection.getHeaderFields();
			List<String> values = headers.get("Type");
			String type = values.get(0);
			
			if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
				InputStream in = connection.getInputStream();
				return determineResponse(type, in);
			}else{
				return null;
			}
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	private Object determineResponse(String type, InputStream in) {
		if (type.equals("ValidateUser_Output")) {
			ValidateUser_Output vuOut = (ValidateUser_Output) xmlStream
					.fromXML(in);
			return vuOut;
		} else if (type.equals("GetProjects_Output")) {
			GetProjects_Output gpOut = (GetProjects_Output) xmlStream
					.fromXML(in);
			return gpOut;
		} else if (type.equals("GetSampleImage_Output")) {
			GetSampleImage_Output gsiOut = (GetSampleImage_Output) xmlStream
					.fromXML(in);
			return gsiOut;
		} else if (type.equals("DownloadBatch_Output")) {
			DownloadBatch_Output dbOut = (DownloadBatch_Output) xmlStream
					.fromXML(in);
			return dbOut;
		} else if (type.equals("SubmitBatch_Output")) {
			SubmitBatch_Output sbOut = (SubmitBatch_Output) xmlStream
					.fromXML(in);
			return sbOut;
		} else if (type.equals("GetFields_Output")) {
			GetFields_Output gfOut = (GetFields_Output) xmlStream.fromXML(in);
			return gfOut;
		} else if (type.equals("Search_Output")) {
			Search_Output searchOut = (Search_Output) xmlStream.fromXML(in);
			return searchOut;
		} else {
			return null;
		}
	}

	public String[] validateUser(ValidateUser_Input input) {

		ValidateUser_Output vuOut = (ValidateUser_Output) doPost(
				"/ValidateUser", input);

		String[] request_response = new String[] { vuOut.getRequest(),
				vuOut.toString() };

		return request_response;
	}

	public String[] getProjects(ValidateUser_Input input) {
		
		GetProjects_Output gpOut = (GetProjects_Output) doPost("/GetProjects",
				input);
		String[] request_response = new String[] { gpOut.getRequest(),
				gpOut.toString() };

		return request_response;
	}

	public String[] getSampleImage(GetSampleImage_Input input) {
		GetSampleImage_Output gsiOut = (GetSampleImage_Output) doPost(
				"/GetSampleImage", input);
		String[] request_response = new String[] { gsiOut.getRequest(),
				gsiOut.toString() };

		return request_response;
	}

	public String downloadBatch(DownloadBatch_Input input) {
		DownloadBatch_Output dbOut = (DownloadBatch_Output) doPost(
				"/DownloadBatch", input);
		return null;
	}

	public String submitBatch(SubmitBatch_Input input) {
		SubmitBatch_Output sbOut = (SubmitBatch_Output) doPost("/SubmitBatch",
				input);
		return null;
	}

	public String getFields(GetFields_Input input) {
		GetFields_Output gfOut = (GetFields_Output) doPost("/GetFields", input);
		return null;
	}

	public String search(Search_Input input) {
		Search_Output searchOut = (Search_Output) doPost("/GetAllProjects",
				input);
		return null;
	}

}
